package com.codecrane.core.power.controller;

import com.codecrane.core.util.BackupUtil;
import com.codecrane.core.web.Ajax;
import com.codecrane.core.web.AjaxReturn;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.net.URLEncoder;
import java.util.*;

/**
 * 数据管理更新模块
 * Created by crane on 17/3/20.
 */
@Slf4j
@Controller
@RequestMapping("/power/dbmanager")
public class DbManagerController {

    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    @Value("${app_backup_store_path}")
    private String backupStorePath;

    /**
     * 数据管理页面
     *
     * @param modelMap
     * @return
     */
    @RequestMapping(value = "/main", method = RequestMethod.GET)
    public String manager(ModelMap modelMap) {

        return "/power/dbmanager/main";
    }


    /**
     * SQL执行
     *
     * @param sql
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/run", method = RequestMethod.POST)
    public AjaxReturn runScript(@RequestParam("sql") String sql) {
        AjaxReturn webResult = Ajax.fail().setMsg("执行失败!");
        if (null != sqlSessionFactory) {
            ScriptRunner scriptRunner = new ScriptRunner(sqlSessionFactory.openSession().getConnection());
            scriptRunner.setAutoCommit(false);
            scriptRunner.setSendFullScript(true);
            scriptRunner.setThrowWarning(true);
            scriptRunner.setStopOnError(true);
            if (StringUtils.isNotBlank(sql)) {
                //TODO 非法sql过滤
                sql = StringUtils.trim(sql);
                Reader reader = new StringReader(sql);
                try {
                    File logFile = new File("sqldebug.log");
                    PrintWriter pw = new PrintWriter(logFile);
                    scriptRunner.setLogWriter(pw);
                    scriptRunner.runScript(reader);
                    webResult.setOk(true).setMsg("执行完毕!").setData(FileUtils.readFileToString(logFile, "utf-8"));
                } catch (Exception e) {
                    e.printStackTrace();
                    webResult.setMsg("执行异常!");
                }
            } else {
                webResult.setMsg("执行的SQL不能为空!");
            }
        }
        return webResult;
    }

    /**
     * 备份数据库
     *
     * @param ip
     * @param user
     * @param password
     * @param port
     * @param database
     * @param filename
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "backup", method = RequestMethod.POST)
    public AjaxReturn doBackup(@RequestParam(value = "ip", defaultValue = "127.0.0.1") String ip,
                               @RequestParam("user") String user,
                               @RequestParam("password") String password,
                               @RequestParam(value = "port", defaultValue = "3306") String port,
                               @RequestParam("database") String database,
                               @RequestParam("filename") String filename) {
        AjaxReturn webResult = Ajax.fail().setMsg("备份失败!");

        if (StringUtils.isNoneBlank(ip, user, password, port, database, filename)) {

            File path = new File(backupStorePath);

            if (!path.exists()) {
                path.mkdir();
            }

            Properties properties = new Properties();
            properties.setProperty("ip", ip);
            properties.setProperty("user", user);
            properties.setProperty("password", password);
            properties.setProperty("port", port);
            properties.setProperty("database", database);
            properties.setProperty("path", backupStorePath);
            properties.setProperty("filename", filename);

            log.debug("cmd :{}", BackupUtil.getExptCmd(properties));
            BackupUtil.ExptSQL(properties);

            webResult.setOk(true).setMsg("备份完成！").setData(backupStorePath + filename);
        }

        return webResult;
    }

    /**
     * 数据库备份配置页面
     *
     * @param modelMap
     * @return
     */
    @RequestMapping(value = "backup_config", method = RequestMethod.GET)
    public String backupConfigPage(ModelMap modelMap) {
        return "/power/dbmanager/backup_config";
    }

    /**
     * 数据库备份文件列表页面
     *
     * @param dir
     * @param modelMap
     * @return
     */
    @RequestMapping(value = "backup_list", method = RequestMethod.GET)
    public String backupListPage(@RequestParam(value = "dir", required = false) String dir, ModelMap modelMap) {

        String targetDir = backupStorePath;
        if (StringUtils.isNotBlank(dir)) {
            targetDir = dir;
        }

        File backupPath = new File(targetDir);

        File[] backupFiles = backupPath.listFiles();

        List<Map<String, Object>> files = new ArrayList<>();
        if (null != backupFiles && backupFiles.length > 0) {
            String osName = System.getProperty("os.name");
            boolean isWindows = osName.contains("Windows");
            for (File file : backupFiles) {
                Map<String, Object> fileInfo = new HashMap<>();
                fileInfo.put("name", file.getName());
                fileInfo.put("lastModified", file.lastModified());
                fileInfo.put("path", isWindows ? file.getPath().replaceAll("\\\\", "/") : file.getPath());
                fileInfo.put("length", file.length());
                fileInfo.put("isDir", file.isDirectory());
                files.add(fileInfo);
            }
        }

        modelMap.addAttribute("files", files);
        modelMap.addAttribute("dir", dir);


        return "/power/dbmanager/list";
    }


    /**
     * 下载数据库备份文件
     *
     * @param sqlFilePath
     * @param sqlFileName
     * @return
     */
    @RequestMapping("/backup_download")
    public ResponseEntity<byte[]> downBackUpSql(@RequestParam("path") String sqlFilePath, @RequestParam("name") String sqlFileName, HttpSession session) {

        //默认文件名称
        String downFileName = sqlFileName;
        try {
            downFileName = URLEncoder.encode(sqlFileName, "UTF-8");//转码解决IE下文件名乱码问题
        } catch (Exception e) {
            e.printStackTrace();
        }
        File downFile = new File(sqlFilePath);

        //Http响应头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", downFileName);
        headers.setContentLength(downFile.length());

        try {
            return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(downFile),
                    headers,
                    HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
}
